﻿using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Storage;
using System.Linq.Expressions;
using wwl.Contract.Dtos.Common;
using wwl.Contract.Interfaces.Common;
using wwl.DataAccess.Context;
using wwl.DataAccess.Extensions;
using wwl.Domain.Entities.Common;

namespace wwl.DataAccess.Repositories.Common
{
  /// <summary>
  /// Entity Framework 数据访问包装类，实现 IEfWrapper 接口
  /// 提供基础CRUD、批量操作、事务控制等数据访问功能，支持灵活的提交策略
  /// </summary>
  public class EfWrapperRepository : IEfWrapper
  {
    /// <summary>
    /// 数据库上下文实例，用于与数据库交互（EF Core核心对象）
    /// </summary>
    private readonly AppDbContext _context;

    /// <summary>
    /// 构造函数，通过依赖注入获取数据库上下文
    /// </summary>
    /// <param name="context">应用数据库上下文（AppDbContext）</param>
    public EfWrapperRepository(AppDbContext context)
    {
      _context = context;
    }

    #region 查询方法
    /// <summary>
    /// 获取指定实体类型的查询集合（带实体跟踪）
    /// 自动过滤已软删除的实体（IsDeleted=false），适用于需要修改实体的场景
    /// </summary>
    /// <typeparam name="T">实体类型，必须继承自BaseEntity（基础实体类）</typeparam>
    /// <returns>可查询的实体集合（IQueryable）</returns>
    public IQueryable<T> Query<T>() where T : BaseEntity
    {
      return _context.Set<T>().Where(x => !x.IsDeleted);
    }

    /// <summary>
    /// 获取指定实体类型的查询集合（无实体跟踪）
    /// 自动过滤已软删除的实体，适用于只读操作，性能更优
    /// </summary>
    /// <typeparam name="T">实体类型，必须继承自BaseEntity</typeparam>
    /// <returns>无跟踪的可查询实体集合</returns>
    public IQueryable<T> QueryNoTracking<T>() where T : BaseEntity
    {
      return _context.Set<T>().AsNoTracking().Where(x => !x.IsDeleted);
    }

    /// <summary>
    /// 根据ID异步查询实体
    /// </summary>
    /// <typeparam name="T">实体类型，必须继承自BaseEntity</typeparam>
    /// <param name="id">实体唯一标识（ID）</param>
    /// <returns>查询到的实体，若不存在则返回null</returns>
    public async Task<T?> GetByIdAsync<T>(string id) where T : BaseEntity
    {
      return await Query<T>().FirstOrDefaultAsync(x => x.Id == id);
    }
    #endregion

    #region 基础操作（带自动提交，兼容原有逻辑）
    /// <summary>
    /// 异步添加单个实体（自动提交到数据库）
    /// 适用于单独添加一个实体的场景，操作完成后立即保存
    /// </summary>
    /// <typeparam name="T">实体类型，必须继承自BaseEntity</typeparam>
    /// <param name="entity">要添加的实体对象</param>
    /// <returns>添加后的实体（包含自动生成的ID等信息）</returns>
    public async Task<T> AddAsync<T>(T entity) where T : BaseEntity
    {
      await AddWithoutSaveAsync(entity);
      await SaveChangesAsync();
      return entity;
    }

    /// <summary>
    /// 异步更新单个实体（自动提交到数据库）
    /// 适用于单独更新一个实体的场景，操作完成后立即保存
    /// </summary>
    /// <typeparam name="T">实体类型，必须继承自BaseEntity</typeparam>
    /// <param name="entity">要更新的实体对象</param>
    /// <returns>更新后的实体</returns>
    public async Task<T> UpdateAsync<T>(T entity) where T : BaseEntity
    {
      UpdateWithoutSave(entity);
      await SaveChangesAsync();
      return entity;
    }

    /// <summary>
    /// 异步硬删除实体（从数据库物理删除，自动提交）
    /// </summary>
    /// <typeparam name="T">实体类型，必须继承自BaseEntity</typeparam>
    /// <param name="id">要删除的实体ID</param>
    /// <returns>删除成功返回true，实体不存在或删除失败返回false</returns>
    public async Task<bool> DeleteAsync<T>(string id) where T : BaseEntity
    {
      var entity = await GetByIdAsync<T>(id);
      if (entity == null) return false;

      _context.Set<T>().Remove(entity);
      return await SaveChangesAsync() > 0;
    }

    /// <summary>
    /// 异步软删除实体（标记IsDeleted=true，逻辑删除，自动提交）
    /// </summary>
    /// <typeparam name="T">实体类型，必须继承自BaseEntity</typeparam>
    /// <param name="id">要删除的实体ID</param>
    /// <returns>软删除成功返回true，实体不存在或操作失败返回false</returns>
    public async Task<bool> SoftDeleteAsync<T>(string id) where T : BaseEntity
    {
      var entity = await GetByIdAsync<T>(id);
      if (entity == null) return false;

      entity.IsDeleted = true;
      entity.UpdatedTime = DateTime.UtcNow;
      return await SaveChangesAsync() > 0;
    }
    #endregion

    #region 无自动提交的操作（用于批量处理或事务控制）
    /// <summary>
    /// 添加单个实体（不自动提交到数据库）
    /// 仅将实体添加到EF上下文跟踪，需手动调用SaveChangesAsync()提交
    /// 适用于多步操作需统一提交的场景
    /// </summary>
    /// <typeparam name="T">实体类型，必须继承自BaseEntity</typeparam>
    /// <param name="entity">要添加的实体对象</param>
    public async Task AddWithoutSaveAsync<T>(T entity) where T : BaseEntity
    {
      await _context.Set<T>().AddAsync(entity);
    }

    /// <summary>
    /// 批量添加实体（不自动提交到数据库）
    /// 一次性添加多个实体到EF上下文跟踪，减少单次提交的数据库交互
    /// </summary>
    /// <typeparam name="T">实体类型，必须继承自BaseEntity</typeparam>
    /// <param name="entities">要批量添加的实体集合</param>
    public async Task AddRangeWithoutSaveAsync<T>(IEnumerable<T> entities) where T : BaseEntity
    {
      await _context.Set<T>().AddRangeAsync(entities);
    }

    /// <summary>
    /// 更新单个实体（不自动提交到数据库）
    /// 仅标记实体为修改状态，需手动调用SaveChangesAsync()提交
    /// </summary>
    /// <typeparam name="T">实体类型，必须继承自BaseEntity</typeparam>
    /// <param name="entity">要更新的实体对象</param>
    public void UpdateWithoutSave<T>(T entity) where T : BaseEntity
    {
      _context.Set<T>().Update(entity);
    }

    /// <summary>
    /// 批量更新实体（不自动提交到数据库）
    /// 一次性标记多个实体为修改状态，适合批量更新场景
    /// </summary>
    /// <typeparam name="T">实体类型，必须继承自BaseEntity</typeparam>
    /// <param name="entities">要批量更新的实体集合</param>
    public void UpdateRangeWithoutSave<T>(IEnumerable<T> entities) where T : BaseEntity
    {
      _context.Set<T>().UpdateRange(entities);
    }

    /// <summary>
    /// 标记实体为删除状态（不自动提交，用于硬删除）
    /// 需手动调用SaveChangesAsync()提交删除操作
    /// </summary>
    /// <typeparam name="T">实体类型，必须继承自BaseEntity</typeparam>
    /// <param name="entity">要删除的实体对象</param>
    public void RemoveWithoutSave<T>(T entity) where T : BaseEntity
    {
      _context.Set<T>().Remove(entity);
    }
    #endregion

    #region 事务与提交控制
    /// <summary>
    /// 手动提交所有变更到数据库
    /// 用于批量操作或多步操作后统一提交，减少数据库交互次数
    /// </summary>
    /// <returns>受影响的数据库记录行数</returns>
    public async Task<int> SaveChangesAsync()
    {
      return await _context.SaveChangesAsync();
    }

    /// <summary>
    /// 开启数据库事务
    /// 确保多步操作的原子性（要么全部成功，要么全部失败），避免数据不一致
    /// <remarks>
    /// 代码中使用步骤：
    /// 1、开启事务（using确保自动释放，即使异常也会清理资源）
    /// using var transaction = await _repository.BeginTransactionAsync();
    /// 2、执行多步数据操作（AddWithoutSaveAsync、UpdateWithoutSave等）
    /// 3、提交事务（所有步骤成功后，确认事务生效）
    /// await transaction.CommitAsync();
    /// 4、出现异常时调用
    /// await transaction.RollbackAsync();
    /// </remarks>
    /// </summary>
    /// <returns>数据库事务对象（IDbContextTransaction），需使用using语句管理</returns>
    public async Task<IDbContextTransaction> BeginTransactionAsync()
    {
      return await _context.Database.BeginTransactionAsync();
    }
    #endregion

    #region 分页查询
    /// <summary>
    /// 异步获取分页结果
    /// 自动处理分页、排序和过滤逻辑，返回包含数据和总记录数的分页对象
    /// </summary>
    /// <typeparam name="T">实体类型，必须继承自BaseEntity</typeparam>
    /// <param name="request">分页请求参数（包含页码、页大小、排序字段等）</param>
    /// <param name="filter">可选的查询过滤条件（Lambda表达式）</param>
    /// <returns>分页结果对象（PagedResult<T>）</returns>
    public async Task<PagedResult<T>> GetPagedAsync<T>(PagedRequest request,
        Expression<Func<T, bool>>? filter = null) where T : BaseEntity
    {
      var query = QueryNoTracking<T>();
      query = query.BuildQuery(request, filter); // 应用分页和过滤（扩展方法）
      return await query.ToPagedResultAsync(request); // 转换为分页结果（扩展方法）
    }
    #endregion
  }
}